package com.objecteffects.ilmp.tumblr.method;

import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;

/**
 * @author Rusty Wright
 */
@JsonInclude(JsonInclude.Include.ALWAYS)
public class Followers {
    private final Meta meta;
    private final FollowersResponse followersResponse;

    // @JsonIgnore
    private final Map<String, Object> additionalProperties = new HashMap<>();

    @JsonCreator
    public Followers(@JsonProperty("meta")
    final Meta _meta, @JsonProperty("response")
    final FollowersResponse _followersResponse) {
        this.meta = Objects.requireNonNull(_meta);
        this.followersResponse = Objects.requireNonNull(_followersResponse);
    }

    @JsonProperty("meta")
    public Meta getMeta() {
        return this.meta;
    }

    @JsonProperty("response")
    public FollowersResponse getResponse() {
        return this.followersResponse;
    }

    @JsonAnyGetter
    public Map<String, Object> getAdditionalProperties() {
        return this.additionalProperties;
    }

    @JsonAnySetter
    public void setAdditionalProperty(final String name, final Object value) {
        this.additionalProperties.put(name, value);
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }

    @Override
    public int hashCode() {
        return HashCodeBuilder.reflectionHashCode(this);
    }

    @Override
    public boolean equals(final Object other) {
        return EqualsBuilder.reflectionEquals(this, other);
    }

    @JsonInclude(JsonInclude.Include.NON_NULL)
    private static class FollowersResponse {
        private final int totalUsers;
        private final List<User> users;

        // @JsonIgnore
        private final Map<String, Object> additionalProperties =
            new HashMap<>();

        @JsonCreator
        public FollowersResponse(@JsonProperty("total_users")
        final int _totalUsers, @JsonProperty("users")
        final User[] _users) {
            this.totalUsers = _totalUsers;
            this.users = Arrays.asList(_users);
        }

        @JsonProperty("total_users")
        public int getTotalUsers() {
            return this.totalUsers;
        }

        @JsonProperty("users")
        public List<User> getUsers() {
            return this.users;
        }

        @JsonAnyGetter
        public Map<String, Object> getAdditionalProperties() {
            return this.additionalProperties;
        }

        @JsonAnySetter
        public void
        setAdditionalProperty(final String name, final Object value) {
            this.additionalProperties.put(name, value);
        }

        @Override
        public String toString() {
            return ToStringBuilder.reflectionToString(this);
        }

        @Override
        public int hashCode() {
            return HashCodeBuilder.reflectionHashCode(this);
        }

        @Override
        public boolean equals(final Object other) {
            return EqualsBuilder.reflectionEquals(this, other);
        }

        @JsonInclude(JsonInclude.Include.NON_NULL)
        private static class User {
            private final String name;
            private final Date updated;
            private final String url;
            private final Boolean following;

            @JsonCreator
            public User(@JsonProperty("name")
            final String _name, @JsonProperty("updated")
            final Date _updated, @JsonProperty("url")
            final String _url, @JsonProperty("following")
            final Boolean _following) {
                this.name = StringUtils.defaultIfBlank(_name, "");
                this.updated = _updated;
                this.url = StringUtils.defaultIfBlank(_url, "");
                this.following = _following;
            }

            // @JsonIgnore
            private final Map<String, Object> additionalProperties =
                new HashMap<>();

            /**
             * @return the name
             */
            @JsonProperty("name")
            public String getName() {
                return this.name;
            }

            /**
             * @return the updated
             */
            @JsonProperty("updated")
            public Date getUpdated() {
                return this.updated;
            }

            /**
             * @return the url
             */
            @JsonProperty("url")
            public String getUrl() {
                return this.url;
            }

            /**
             * @return the following
             */
            @JsonProperty("following")
            public Boolean getFollowing() {
                return this.following;
            }

            @JsonAnyGetter
            public Map<String, Object> getAdditionalProperties() {
                return this.additionalProperties;
            }

            @JsonAnySetter
            public void setAdditionalProperty(final String _name,
                final Object value) {
                this.additionalProperties.put(_name, value);
            }

            @Override
            public String toString() {
                return ToStringBuilder.reflectionToString(this);
            }

            @Override
            public int hashCode() {
                return HashCodeBuilder.reflectionHashCode(this);
            }

            @Override
            public boolean equals(final Object other) {
                return EqualsBuilder.reflectionEquals(this, other);
            }
        }
    }
}
